# -*- coding: euc-jp -*-

require "socket"
require "component_manager.rb"
require "parameter.rb"
require "debugout.rb"

class CNCServer
  def initialize(parameter, component_manager)
    @parameter = parameter
    port = @parameter.get("cncserver.port")
    @component_manager = component_manager
    @gsock = TCPServer.open(port)
    Debugout.puts(Debugout::LEVEL_INFO, "server is on %s\n" % [addr_str])
  end

  def addr_str
    addr = @gsock.addr
    addr.shift
    return addr.join(":")
  end

  def main_loop
    while true
      s = @gsock.accept
      Debugout.puts(Debugout::LEVEL_INFO, "peer addr = %s\n" % [s.addr.join(":")])
      while s.gets
        result = do_request($_)
        if result.class == Array
          result_str = "[" + result.join(",") + "]"
        else
          result_str = result.to_s
        end
        s.puts result_str
      end
      Debugout.puts(Debugout::LEVEL_INFO, "disconnect.\n")
    end
  end

  def do_request(req)
    result = nil
    begin
      token = req.split(" ")
      comp, func = token.shift.split(".").map{|v| v.intern}
      args = token.map{|v| eval(v)} # convert args (it is not safe. to be modified.)
      result = @component_manager.call_func(comp, func, args)
      Debugout.puts(Debugout::LEVEL_DEBUG, "%s.%s (%s) --> \n" % [ comp, func, token.join(","), result])
    rescue
      Debugout.puts(Debugout::LEVEL_ERROR, "Error: #$!")
      result = "Error: #$!"
    end
    return result
  end
end

Debugout.set_output_level(Debugout::LEVEL_DEBUG_MORE)

if ARGV.length != 1 then
  STDERR.puts "usage: cncserver parameter-file-name"
  exit
end

parameter_file_name = ARGV.shift
parameter = Parameter.new(parameter_file_name)

comp_manager = ComponentManager.new(parameter)

cncserver = CNCServer.new(parameter, comp_manager)
cncserver.main_loop
